﻿using Inaction.Core;
using Inaction.Mapping;
using Inaction.ServiceContract;
using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace Inaction.Business
{
    public partial class Entity<T> : IDataErrorInfo
        where T : Entity<T>, new()
    {
        #region  IDataErrorInfo
        [Browsable(false)]
        public string Error
        {
            get
            {
                if (!IsDirty) return string.Empty;
                var error = string.Empty;
                CheckError(out error, (System.Data.IDbTransaction)null);
                return error;
            }
        }
        public string this[string columnName]
        {
            get
            {
                if (AppConfig.Instance.RunLocation == RunLocation.Server) return string.Empty;
                var error = string.Empty;
                CheckPropertyError(out error, columnName);
                return error;
            }
        }
        public bool CheckError(out string error, string propertyName, object value)
        {
            error = string.Empty;
            if (!ClassInfo.NameProperties.ContainsKey(propertyName)) return false;
            var property = ClassInfo.NameProperties[propertyName];
            var val = value;
            foreach (var validate in property.ValidateAttributes)
            {
                if (!validate.IsValid(val))
                {
                    error += validate.FormatErrorMessage(property.DisplayName) + Environment.NewLine;
                }
            }
            if (PropertyRules.ContainsKey(property))
            {
                foreach (var propertyRule in PropertyRules[property])
                {
                    var s = propertyRule.Invoke((T)this, null);
                    if (!string.IsNullOrEmpty(s))
                    {
                        error += s + Environment.NewLine;
                    }
                }
            }
            return string.IsNullOrEmpty(error);
        }
        public virtual bool CheckPropertyError(out string error, string propertyName, System.Data.IDbTransaction trans = null)
        {
            error = string.Empty;
            base.CheckPropertyError(out error, propertyName, trans);
            if (!ClassInfo.NameProperties.ContainsKey(propertyName)) return false;
            var property = ClassInfo.NameProperties[propertyName];
            return CheckPropertyError(out error, property, trans);
        }
        public override bool CheckPropertyError(out string error, IProperty property, System.Data.IDbTransaction trans = null)
        {
            error = string.Empty;
            if (!IsNew && !IsPropertyDirty(property)) return false;
            base.CheckPropertyError(out error, property, trans);
            if (PropertyRules.ContainsKey(property))
            {
                foreach (var propertyRule in PropertyRules[property])
                {
                    var s = propertyRule.Invoke((T)this, trans);
                    if (!string.IsNullOrEmpty(s))
                    {
                        error += s + Environment.NewLine;
                    }
                }
            }
            return !string.IsNullOrEmpty(error);
        }

        public override bool CheckError(out string error, System.Data.IDbTransaction trans = null)
        {
            error = string.Empty;
            if (!IsNew && !IsSelfDirty && !IsDeleted) return false;
            base.CheckError(out error, trans);
            foreach (var rule in EntityRules)
            {
                var s = rule.Invoke((T)this, trans);
                if (!string.IsNullOrEmpty(s))
                {
                    error += s + Environment.NewLine;
                }
            }
            return !string.IsNullOrEmpty(error);
        }
        #endregion
    }
}